Porgramming Language 1
2015-11-04
Porgramming Language 1
前言
刚刚结束这门课的期中考试,老师讲课内容很深,考试也很难,并且提高了自己对编程语言的理解,有必要做一个记录。
这一部分对应的是Fortran和Algol60。
Fortran
一些重要的概念:
- Functions(not subroutines)
- Common blocks
- Definete loops
- Operateor overloading(not user-defined)
- on intergers and reals
- Type coersion
在Fortran里,二维数组是按列存储的。这点比较反人类。并且所有的数据都是静态分配的(后面会提到动态分配)。 最重要的是理解GOTO这个关键字的意义和对后来者的影响。 Programming 作业就是用Fortran实现一个BNF(可以理解成写正则表达式)。
Algol60
这是First design-by-commitee language。
一些重要的概念:
- IF was an expression not a statement
- Block structure and scoping rules
- Structured, nestablecontrol statements
- Dynamic bounds on arrays
- Call by value and call by name for procedure parameters
- Dynamic variable lifetime*
- BNF –Backus-Naur Form
- Recursion (and thus, stack-based computation model)
加粗部分是比较重要的概念,像Java,Python都有用到这些方法。
statement vs expression
如果有疑问,可以参考这里
variable
Address
- Variables may not live at the same address
- Multiple variables may share an address: aliasing
- This can change as the program changes
1 #include <stdio.h>
2 intmain() {
3 char *x = "This is an example";
4 char *y = x;
5 printf("%p\n", y);
6 y = NULL;
7 printf("%p\n", y);
8 }
0x1053e3f7a
0x0
熟悉c的同学这段代码应该没问题的。
Binding
绑定,在这里指的是变量和内存地址的绑定,主要分为3个阶段:
- compile time: 一些全局变量或者const等
- load time:静态变量。 我自己理解这里花了很长的时间,不太懂load time是哪一段时间,看了下wiki:https://en.wikipedia.org/wiki/Run_time_(program_lifecycle_phase) 才明白的,简而言之,load time就是运行程序时,程序在内存中,这个时候,loader会扫描程序,分配地址,一切完成后,程序才运行,就到了run time。
- run time:这里比较复杂,有些语言是stack allocation的,在函数中的变量就会不断的绑定和销毁。
总结一下:
Static binding: happens before runtime
Dynamic binding: happens during runtime
Scope & Lifetime
这2个是特别容易混淆的概念。Scope是指变量有意义的范围,Lifetime就是生命周期。乍一看起来,2者是一样的,其实对不同的编程语言,有很大的区别。
- Scope
float pi = 3.1415927;
float calc_area(float r) {
return pi * r * r;
}
很显然,在calc_area()
函数中可以知道pi的值,也就是说pi的scope包括了calc_area()
函数。这是静态的。
动态:
func f1() {
x = 10;
f2();
}
func f2() {
print(x);
print(z);
}
x = 1;
z = 1;
f1();
f2();
输出结果是10,1,1,1 dynamic scoping 是上下文相关的。
流程图:
当需要x变量时,函数会不断往外寻找,这就是动态的原因。
2.lifetime
char *copy(char *str) {
inti, l;
l = strlen(str);
char *ret = (char *)malloc(l);
for (i=0; i<= l; i++) {
ret[i] = str[i];
}
return ret;
}
对于这段代码,copy()函数结束后,变量ret就销毁了吗? 并不是这样的。ret是通过malloc得来的,此时,ret并不是存在stack中,而是存在heap中。(不太懂得同学可以参考这里或者百度,上面有很多解释。)这样,只有programmer调用free时,ret变量才会被内存销毁。 所以,ret的lifetime比scope要大。
总结一下就是:
Static allocation: statically bound to a memory address(整个run time)
Stack allocation: local variable w/ automatic allocation
Heap allocation: dynamically allocated at runtime (via mallocor similar)
Parameter passing 这也是很重要的概念。 熟悉C语言的同学都知道,C是值传递的(pass-by-value),调用swap(int a,int b)并不难交换2个数。
- pass-by-name: 只有在需要的时候才赋值。
x=[1,2,3,4,5,6,7,8,9,10]
i=10
int sum(ix,l.u,item){
s=0
for(ix=l; ix <= u; ix++){
s=s+item
}
}
sum(i,1,10,x[i])
结果是55,而不是100。 因为x[i]并不是在传参的时候被实例化了,而是在
s=s+item
中才被赋值。
pass-by-value: C语言使用的就是这个,没什么好说的。不过,在java和Python中,基本类型也是使用的这个,而高级类型(如:对象)使用的是pass-by-reference
pass-by-reference: 相当于有一个指针指向了变量,在函数内部,形参改变了,实参也改变了。因为这2者是指向同一个地址的。
pass-by-result:和pass-by-reference差不多,也是和实参指向同一个地址,但是,区别在于,pass-by-result的形参不能读取,只能输出。
pass-by-value-resule:可以理解成copy in & copy out,效果可pass-by-reference一样。
最后附上他们的优缺点:
- Pass-by-name
- -Too unintuitive
- -Parameters evaluated each use –could get expensive in a loop
- Pass-by-reference
- +More efficient than copying
- -Aliasing leads to unexpected side-effects
- -How to handle an expression as an argument?
- Pass-by-value
- +Argument protected from changes in callee
- +No unintended side-effects
- -Execution time and space, especially for arrays, etc.
- Pass-by-result
- +Manifest interface
- -fnfunc(a, b : int); func(m, m);
Category: class_study Tagged: class